package cn.agiledata.bank.scores.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;

import cn.agiledata.bank.account.dao.IAccountDAO;
import cn.agiledata.bank.common.dao.SysTemplate;
import cn.agiledata.bank.common.exception.BusinessException;
import cn.agiledata.bank.common.service.email.ScoreActivateEmail;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.PageBean;
import cn.agiledata.bank.common.util.WeatherUtil;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.AccountGroups;
import cn.agiledata.bank.hibernateBean.Groups;
import cn.agiledata.bank.hibernateBean.ScoresHis;
import cn.agiledata.bank.hibernateBean.ScoresRules;
import cn.agiledata.bank.hibernateBean.SysParameter;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.myspace.service.AuthenticateService;
import cn.agiledata.bank.scores.dao.HisScoresQueryPageListPage;
import cn.agiledata.bank.scores.dao.IScoresDAO;
import cn.agiledata.bank.scores.form.HisScoresQueryBean;
import com.vnv.infrastructure.logic.IPBAppFactory;

public class ScoresServiceImpl implements IScoresService {
	private static Log log = LogFactory.getLog(ScoresServiceImpl.class);

	private IScoresDAO scoresDao;

	private IAccountDAO accountDAO;

	private AuthenticateService authenticateService;

	public void setAuthenticateService(AuthenticateService authenticateService) {
		this.authenticateService = authenticateService;
	}

	public void setAccountDAO(IAccountDAO accountDAO) {
		this.accountDAO = accountDAO;
	}

	public void setScoresDao(IScoresDAO scoresDao) {
		this.scoresDao = scoresDao;
	}

	// 获得积分规则
	public ScoresRules getScoresRule(String scoresSource, String accountId) {
		ScoresRules sr = null;
		String grading = null;

		Account acc = this.accountDAO.getAccountById(new Long(accountId));

		for (Iterator iter = acc.getAccountGroupses().iterator(); iter
				.hasNext();) {
			AccountGroups ag = (AccountGroups) iter.next();
			Groups group = ag.getGroups();
			if (group.getGroupType().equals(Constant.GROUP_TYPE_C)) {
				grading = group.getId().toString();
			}
		}

		List ls = scoresDao.getScoresRule(scoresSource, grading, new Date());
		if (ls == null)
			return sr;
		// 根据积分优先级来取积分规则
		for (int i = 0, s = ls.size(); i < s; i++) {
			sr = (ScoresRules) ls.get(i);
			if (!sr.getPriority().equals(Constant.SCORES_PRIORITY_A))
				break;
		}
		return sr;
	}

	// 根据accountId返回积分历史中的累计积分
	private Double getTotalScoresByHistory(String accountId) {
		Double totalScores = null;
		ScoresHis sh = null;
		List ls = scoresDao.getScoresHis(accountId);
		if (ls.size() == 0) {
			totalScores = new Double(0.00);
		} else {
			sh = (ScoresHis) ls.get(0);
			totalScores = (Double) sh.getTotalScores();
		}
		return totalScores;
	}

	// 根据积分方法计算积分
	private Double getScoresAmount(ScoresRules sr, Transaction tran,
			Long deposits, Account account) {
		double scoresAmount = 0.00;
		if (sr == null) {
			return new Double(0);
		}
		if (!Constant.SCORES_METHOD_B.equals(sr.getMethod())) {
			scoresAmount = sr.getScoresAmount().doubleValue();
		} else {
			if (tran == null && deposits != null) {
				scoresAmount = deposits.longValue()
						/ (sr.getMoneyAmount().longValue() * 30)
						* sr.getScoresAmount().longValue();
			} else {
				if (tran.getAmount().doubleValue() < 1) {
					scoresAmount = 0 ;
				} else {
					scoresAmount = (setScoresScale(tran.getAmount().doubleValue(),
							sr).doubleValue() / sr.getMoneyAmount().doubleValue())
							* sr.getScoresAmount().doubleValue();
				}
			}
			// 如果本次交易积分超过最大值，取最大值
			if (sr.getUpperLimit() != null
					&& scoresAmount > sr.getUpperLimit().doubleValue())
				scoresAmount = sr.getUpperLimit().doubleValue();
			
			// zln 修正 2008-1-23 增加月度积分上限
			Double dbTotalScoreM = scoresDao.getMonthScore(account);
			
			// 取得系统参数中积分上限限制
			SysTemplate sysTemplate = (SysTemplate) IPBAppFactory
					.getObj("sysTemplate");
			SysParameter scoreLimite = sysTemplate.getMonthScoreLimite(account.getId());
			
			Double dbLimite = new Double(scoreLimite.getParmValue());
			
			// 判断当前获得积分以后是否超过月度积分限额
			if((dbTotalScoreM.doubleValue() + scoresAmount) > dbLimite.doubleValue()) {
				// 大于积分限额，当前实际获得积分为限额－当月获得积分
				scoresAmount = dbLimite.doubleValue() - dbTotalScoreM.doubleValue();
			}
		}
		return new Double(scoresAmount);
	}

	// 根据不同的小数处理方法处理积分
	private Double setScoresScale(double scores, ScoresRules sr) {
		String scoresAmount = null;

		if (sr.getMoneyAmountType().equals(Constant.DECIMAL_FRACTION_METHOD_A)) {
			// 保留小数
			scoresAmount = new Double(scores).toString();
		}
		if (sr.getMoneyAmountType().equals(Constant.DECIMAL_FRACTION_METHOD_B)) {
			// 取整
			BigDecimal bd = new BigDecimal(scores);
			scoresAmount = new Double(bd.setScale(0, BigDecimal.ROUND_DOWN)
					.intValue()).toString();
		} else if (sr.getMoneyAmountType().equals(
				Constant.DECIMAL_FRACTION_METHOD_C)) {
			// 四舍五入
			BigDecimal bd = new BigDecimal(scores);
			scoresAmount = (new Double(bd.setScale(0, BigDecimal.ROUND_HALF_UP)
					.intValue())).toString();
		}
		return new Double(scoresAmount);
	}

	// 激活用户并记录积分历史

	public ScoresHis saveScoresHistory(String accountId, ScoresRules sr,
			Transaction tran, Long deposits) {
		Account acc = accountDAO.getAccountById(new Long(accountId));

		// 判断是否个人用户
		if (acc.getAccountType().equals(Constant.ACCOUNT_TYPE_BUYER)) {
			ScoresHis sh = new ScoresHis();
			sh.setAccount(acc);

			sh.setScoresRules(sr);
			sh.setScoresAmount(getScoresAmount(sr, tran, deposits, acc));
			if (sh.getTotalScores() == null) {
				sh.setTotalScores(new Double(0.00));
			}
			// 计算scoreshistory中的累计积分
			sh.setTotalScores(new Double(getTotalScoresByHistory(
					acc.getId().toString()).doubleValue()
					+ sh.getScoresAmount().doubleValue()));
			// 更新account中的累计积分
			if (acc.getTotalScores() == null) {
				acc.setTotalScores(new Double(0.00));
			}
			acc.setTotalScores(sh.getTotalScores());
			sh.setAccount(acc);
			// 判断是否存在transaction对象
			if (tran != null) {
				sh.setTransaction(tran);
			}
			WeatherUtil.fillCreateAndUpdateInfo(sh, accountId);

			saveOrUpdateScoresHis(sh);

			return sh;
		}
		return new ScoresHis();
	}
	public void saveOrUpdateScoresHisWithoutFlush(ScoresHis sh) {
		// TODO Auto-generated method stub
		try {
			scoresDao.saveOrUpdateScoresHisWithoutFlush(sh);
		} catch (DataAccessException e) {
			log.error("数据库操作错误", e);
			throw BusinessException.INFRA_FAILURE;
		}
	}
	
	public void saveOrUpdateScoresHis(ScoresHis sh) {
		// TODO Auto-generated method stub
		try {
			scoresDao.saveOrUpdateScoresHistory(sh);
		} catch (DataAccessException e) {
			log.error("数据库操作错误", e);
			throw BusinessException.INFRA_FAILURE;
		}
	}

	// 锟斤拷锟斤拷锟斤拷锟斤拷
	public void setDepositsScores(Account acc, Long deposits) {
		if (acc.getAccountType().equals(Constant.ACCOUNT_TYPE_BUYER)
				&& deposits.longValue() > 0) {
			saveScoresHistory(acc.getId().toString(), getScoresRule(
					Constant.SCORES_SOURCE_E, acc.getId().toString()), null,
					deposits);
		}
	}

	private ScoresHis saveScoresHis(String accountId, ScoresRules sr) {
		Account acc = accountDAO.getAccountById(new Long(accountId));

		// 判断是否个人用户
		if (acc.getAccountType().equals(Constant.ACCOUNT_TYPE_BUYER)) {
			ScoresHis sh = new ScoresHis();
//			sh.setAccount(acc);

			sh.setScoresRules(sr);
			sh.setScoresAmount(getScoresAmount(sr, null, null, acc));
			if (sh.getTotalScores() == null) {
				sh.setTotalScores(new Double(0.00));
			}
			// 计算scoreshistory中的累计积分
			sh.setTotalScores(new Double(getTotalScoresByHistory(
					acc.getId().toString()).doubleValue()
					+ sh.getScoresAmount().doubleValue()));
			// 更新account中的累计积分
			if (acc.getTotalScores() == null) {
				acc.setTotalScores(new Double(0.00));
			}
			acc.setTotalScores(sh.getTotalScores());
			sh.setAccount(acc);
			// 判断是否存在transaction对象

			WeatherUtil.fillCreateAndUpdateInfo(sh, accountId);
			saveOrUpdateScoresHis(sh);
			return sh;
		}
		return new ScoresHis();
	}

	public void setActivationStatus(Long accountId, String url) {
		Account acc = accountDAO.getAccountById(accountId);
		if (mobileStatus(acc)
				|| bankCardStatus(acc)
				|| idCardStatus(acc)
						.equals(Constant.AUTHENTICATION_STATUS_PASS)) {
			acc.setActivateStatus(Constant.SCORES_ACTIVATE_STATUS_B);
			ScoresHis sh = saveScoresHis(acc.getId().toString(), getScoresRule(
					Constant.SCORES_SOURCE_B, acc.getId().toString()));
			ScoreActivateEmail sa = (ScoreActivateEmail) IPBAppFactory
					.getObj("scoreActiveMail");
			sa.setUrl(url);
			sa.sendMail(null, sh);
		}
	}

	public void setActivationStatus(Long accountId) {
		Account acc = accountDAO.getAccountById(accountId);
		if (mobileStatus(acc)
				|| bankCardStatus(acc)
				|| idCardStatus(acc)
						.equals(Constant.AUTHENTICATION_STATUS_PASS)) {
			acc.setActivateStatus(Constant.SCORES_ACTIVATE_STATUS_B);
			saveScoresHis(acc.getId().toString(), getScoresRule(
					Constant.SCORES_SOURCE_B, acc.getId().toString()));
		}
	}

	// 返回用户账户的激活状态
	public String activationStatus(String accountId) {
		Account acc = accountDAO.getAccountById(new Long(accountId));
		ScoresHis sh = new ScoresHis();
		if (mobileStatus(acc)
				|| bankCardStatus(acc)
				|| idCardStatus(acc)
						.equals(Constant.AUTHENTICATION_STATUS_PASS)) {
			if (Constant.SCORES_ACTIVATE_STATUS_A.equals(acc
					.getActivateStatus())) {
				// 如果满足积分激活条件，直接激活
				acc.setActivateStatus(Constant.SCORES_ACTIVATE_STATUS_B);
				setIntroduceScores(acc);
				sh = saveScoresHistory(acc.getId().toString(), getScoresRule(
						Constant.SCORES_SOURCE_B, acc.getId().toString()),
						null, null);
				// 发送激活邮件
				ScoreActivateEmail sa = (ScoreActivateEmail) IPBAppFactory
						.getObj("scoreActiveMail");
				sa.setUrl("");
				sa.sendMail(null, sh);
				if (sh.getScoresAmount().doubleValue()==0) {
					return "0";
				} else {
					return sh.getScoresAmount().toString();
				}
			} else {
				return "";
			}
		} else {
			return "";
		}
	}

	// 判断是否存在有效交易
	public boolean bankCardStatus(Account account) {
		if (authenticateService.feasibleBankCardAuthentication(account)) {
			// 您的银行卡成功验证
			authenticateService.setBankCardAuthenticationStatus(account,
					Constant.AUTHENTICATION_STATUS_PASS);
			return true;
		} else {
			// 您的银行卡未能通过验证，您需要使用您的银行卡进行冲值或者提现交易，再申请验证
			authenticateService.setBankCardAuthenticationStatus(account,
					Constant.AUTHENTICATION_STATUS_UNPASS);
			return false;
		}
	}

	// 判断身份证认证状态
	public String idCardStatus(Account account) {
		return authenticateService.getIdcardAuthenticationStatus(account);
	}

	// 判断手机绑定状态
	public boolean mobileStatus(Account account) {
		String status = authenticateService
				.getMobileTelAuthenticationStatus(account);
		if (StringUtils.isNotEmpty(status)
				&& status.equals(Constant.AUTHENTICATION_STATUS_PASS)) {
			return true;
		} else {
			return false;
		}
	}

	// 设置介绍人积分
	public void setIntroduceScores(Account acc) {
		if (acc.getIntroduceAccountId() != null) {
			Account intrAcc = accountDAO.getAccountById(acc
					.getIntroduceAccountId());
			if (StringUtils.isEmpty(intrAcc.getActivateStatus()))
				intrAcc.setActivateStatus(Constant.SCORES_ACTIVATE_STATUS_A);
			if (intrAcc.getActivateStatus().equals(
					Constant.SCORES_ACTIVATE_STATUS_B)) {
				saveScoresHistory(intrAcc.getId().toString(), getScoresRule(
						Constant.SCORES_SOURCE_H, intrAcc.getId().toString()),
						null, null);
			}
		}
		List ls = scoresDao.getIntroduceList(acc.getId().toString());
		if (!ls.isEmpty()) {
			for (Iterator iter = ls.iterator(); iter.hasNext();) {
				Account intrAccount = (Account) iter.next();
				if (intrAccount.getActivateStatus().equals(
						Constant.SCORES_ACTIVATE_STATUS_B)) {
					saveScoresHistory(intrAccount.getId().toString(),
							getScoresRule(Constant.SCORES_SOURCE_H, intrAccount
									.getId().toString()), null, null);
				}
			}
		}
	}

	public Account getAccountById(String id) {
		return accountDAO.getAccountById(new Long(id));
	}

	// 积分历史分页查询
	public PageBean getHisScoresQueryPagingList(HisScoresQueryBean bean) {
		HisScoresQueryPageListPage listPage = new HisScoresQueryPageListPage(
				bean);
		PageBean pb = listPage.getAccountListPageBean();
		return pb;
	}

	// 获得积分来源
	public List getScoresSource() {
		return scoresDao.getScoresSource();
	}

	// 返回已通过认证项
	public String getAuthenticateStatus(Account account) {
		String bank = authenticateService
				.getBankCardAuthenticationStatus(account);
		String idCard = authenticateService
				.getIdcardAuthenticationStatus(account);
		String mobile = authenticateService
				.getMobileTelAuthenticationStatus(account);
		StringBuffer sb = new StringBuffer();
		if (StringUtils.isNotEmpty(bank)
				&& bank.equals(Constant.AUTHENTICATION_STATUS_PASS))
			sb.append("银行卡 ");
		if (StringUtils.isNotEmpty(idCard)
				&& idCard.equals(Constant.AUTHENTICATION_STATUS_PASS))
			sb.append("身份证 ");
		if (StringUtils.isNotEmpty(mobile)
				&& mobile.equals(Constant.AUTHENTICATION_STATUS_PASS))
			sb.append("手机 ");
		return sb.toString();
	}

	// 积分计算
	public String calcScores(Account account, Double scores, String source) {
		if (StringUtils.isEmpty(account.getActivateStatus())
				|| !account.getActivateStatus().equals(
						Constant.SCORES_ACTIVATE_STATUS_B)
				|| !account.getAccountType()
						.equals(Constant.ACCOUNT_TYPE_BUYER)) {
			return Constant.DEDUCE_SCORES_C;
		} else if (account.getTotalScores().doubleValue() < scores
				.doubleValue()) {
			return Constant.DEDUCE_SCORES_B;
		} else {
			ScoresHis sh = new ScoresHis();
			sh.setAccount(account);
			sh.setScoresActivityId(Constant.ACTIVITY);
			sh.setScoresAmount(scores);
			
			//add by cjh 扣减积分的来源
			ScoresRules sr = this.getScoresRule(source,String.valueOf(account.getId()));
			sh.setScoresRules(sr);//设置积分规则
			
			if (sh.getTotalScores() == null) {
				sh.setTotalScores(new Double(0.00));
			}
			// 计算scoreshistory中的累计积分
			sh.setTotalScores(new Double(getTotalScoresByHistory(
					account.getId().toString()).doubleValue()
					+ sh.getScoresAmount().doubleValue()));
			// 更新account中的累计积分
			if (account.getTotalScores() == null) {
				account.setTotalScores(new Double(0.00));
			}
			account.setTotalScores(new Double(account.getTotalScores()
					.doubleValue()
					+ sh.getScoresAmount().doubleValue()));

			WeatherUtil.fillCreateAndUpdateInfo(sh, account.getId().toString());
			saveOrUpdateScoresHisWithoutFlush(sh);
			return Constant.DEDUCE_SCORES_A;
		}
	}

	public ScoresHis getScoresHis(Long id, String scoresSource, Long transId) {
		return scoresDao.getScoresHis(id, scoresSource, transId);
	}
	
	//获取当前使用的所有积分规则
	public List getCurScoresRule(Long id) {
		return scoresDao.getCurScoresRule(id);
	}
}